/*
 * SplitPaneDelegate.cpp  0.4.0 / Dec 05, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
#include "SplitPaneDelegate.h"

// SplitPaneDelegate :: Protected Constructor. ---------------------------------

/*!
 * \brief Constructs new SplitPane Delegate object.
 *
 * \param env the JNIEnv pointer
 * \param obj the SplitPane java object
 */
SplitPaneDelegate::SplitPaneDelegate(JNIEnv *env, jobject obj)
  : ComponentDelegate(env, obj, new QSplitterAdapter())
{
  connectDirect(qSplitterAdapter(), SIGNAL(splitterMoved(int, int)),
                SLOT(splitterMovedSlot(int, int)));
}

// SplitPaneDelegate :: Native Calls. ------------------------------------------

/*!
 * \brief Sets left component of the split pane.
 *
 * \param env the JNIEnv pointer
 * \param componentDelegate the left component delegate
 */
void SplitPaneDelegate::setLeftComponent(JNIEnv *env, jlong componentDelegate)
{
  Q_ASSERT(env);
  SWING_REENTRANT(setLeftComponent, SWING_ENV_ARG, JLONG_ARG(componentDelegate))
  if (componentDelegate) {
    qSplitterAdapter()->insertWidget(0,
                            COMPONENT_CAST(componentDelegate)->qWidget());
  } else {
    qSplitterAdapter()->widget(0)->setParent(0);
  }
}

/*!
 * \brief Sets right component of the split pane.
 *
 * \param env the JNIEnv pointer
 * \param componentDelegate the right component delegate pointer
 */
void SplitPaneDelegate::setRightComponent(JNIEnv *env, jlong componentDelegate)
{
  Q_ASSERT(env);
  SWING_REENTRANT(setRightComponent, SWING_ENV_ARG,
                  JLONG_ARG(componentDelegate))
  if (componentDelegate) {
    qSplitterAdapter()->insertWidget(1,
                            COMPONENT_CAST(componentDelegate)->qWidget());
  } else {
    QWidget *rightWidget = qSplitterAdapter()->widget(1);
    if (!rightWidget) {
      rightWidget = qSplitterAdapter()->widget(0);
    }
    rightWidget->setParent(0);
  }
}

/*!
 * \brief Sets orientation of the split pane.
 *
 * \param env the JNIEnv pointer
 * \param orientation the orientation
 */
void SplitPaneDelegate::setOrientation(JNIEnv *env, jint orientation)
{
  Q_ASSERT(env);
  SWING_REENTRANT(setOrientation, SWING_ENV_ARG, JINT_ARG(orientation))
  switch(orientation) { // do not cast
    case 0:
      qSplitterAdapter()->setOrientation(Qt::Horizontal);
      break;
    case 1:
      qSplitterAdapter()->setOrientation(Qt::Vertical);
      break;
    default:
      LOG_WARNING("Invalid orientation");
      break;
  }
}

/*!
 * \brief Sets whether or not the resizing of components is opaque
 *
 * \param env the JNIEnv pointer
 * \param continuousLayout \c true if opaque
 */
void SplitPaneDelegate::setContinuousLayout(JNIEnv *env,
                                            jboolean continuousLayout)
{
  Q_ASSERT(env);
  SWING_REENTRANT(setContinuousLayout, SWING_ENV_ARG,
                  JBOOLEAN_ARG(continuousLayout))
  qSplitterAdapter()->setOpaqueResize(continuousLayout);
}

/*!
 * \brief Sets resize weight.
 *
 * \param env the JNIEnv pointer
 * \param resizeWeight the resize weight
 */
void SplitPaneDelegate::setResizeWeight(JNIEnv *env, jdouble resizeWeight)
{
  Q_ASSERT(env);
  SWING_REENTRANT(setResizeWeight, SWING_ENV_ARG, JDOUBLE_ARG(resizeWeight))
  qSplitterAdapter()->setResizeWeight(resizeWeight);
}

/*!
 * \brief Returns divider size.
 *
 * \param env the JNIEnv pointer
 * 
 * \return divider size
 */
jint SplitPaneDelegate::getDividerSize(JNIEnv *env)
{
  Q_ASSERT(env);
  SWING_REENTRANT_RETURN(getDividerSize, jint, SWING_ENV_ARG)
  return qSplitterAdapter()->handleWidth();
}

/*!
 * \brief Sets divider size.
 *
 * \param env the JNIEnv pointer
 * \param dividerSize the divider size
 */
void SplitPaneDelegate::setDividerSize(JNIEnv *env, jint dividerSize)
{
  Q_ASSERT(env);
  SWING_REENTRANT(setDividerSize, SWING_ENV_ARG, JINT_ARG(dividerSize))
  qSplitterAdapter()->setHandleWidth(dividerSize);
}

/*!
 * \brief Sets divider location.
 *
 * \param env the JNIEnv pointer
 * \param dividerLocation the divider location
 */
void SplitPaneDelegate::setDividerLocation(JNIEnv *env, jint dividerLocation)
{
  Q_ASSERT(env);
  SWING_REENTRANT(setDividerLocation, SWING_ENV_ARG,
                  JINT_ARG(dividerLocation))
  qSplitterAdapter()->setHandlePosition(dividerLocation);
}

/*!
 * \brief Sets whether or not the comopnents of the split pane can be quickly
 *        expanded/collapsed.
 *
 * \param env the JNIEnv pointer
 * \param oneTouchExpandable \c true if expandable
 */
void SplitPaneDelegate::setOneTouchExpandable(JNIEnv *env,
                                              jboolean oneTouchExpandable)
{
  Q_ASSERT(env);
  SWING_REENTRANT(setOneTouchExpandable, SWING_ENV_ARG,
                  JBOOLEAN_ARG(oneTouchExpandable))
  qSplitterAdapter()->setOneTouchExpandable(oneTouchExpandable);
}

// SplitPaneDelegate :: Static Native Calls. -----------------------------------

/*!
 * \brief Initializes SplitPaneDelegate class.
 *
 * \param env the JNIEnv pointer
 * \param cls the SplitPane java class
 */
void SplitPaneDelegate::initialize(JNIEnv *env, jclass cls)
{
  Q_ASSERT(env);
  Q_ASSERT(cls);
  Q_ASSERT(!sm_dividerLocationChangedMID);
  if (!INIT_UMID(dividerLocationChanged, cls, "(I)V")) {
    FATAL_LOGGED_ERROR("SplitPaneDelegate initialization failed");
  }
}

/*!
 * \brief Returns new instance of the delegate object
 *
 * \param env the JNIEnv pointer
 * \param obj the Swing object
 * 
 * \return new instance of the delegate object
 */
jlong SplitPaneDelegate::newInstance(JNIEnv *env, jobject obj)
{
  if (JNISwingWrapper::isSwingThread(env)) {
    return reinterpret_cast<jlong>(new SplitPaneDelegate(env, obj));
  }
  return SwingUtilitiesDelegate::invokeLongAndWait(env, obj, createMID());
}

// SplitPaneDelegate :: Native Callbacks. --------------------------------------

/*!
 * \brief Calls \c dividerLocationChanged method of the split pane object.
 *
 * \param dividerLocation the divider location
 */
void SplitPaneDelegate::dividerLocationChanged(jint dividerLocation)
{
  jniObject()->callVoidMethod(sm_dividerLocationChangedMID, dividerLocation);
}

// SplitPaneDelegate :: Protected Method. --------------------------------------

/*!
 * \brief splitterMoved slot.
 *
 * \param position the position
 * \param index the index
 */
void SplitPaneDelegate::splitterMovedSlot(int position, int index)
{
  Q_ASSERT(index == 1);
  Q_UNUSED(index);
  dividerLocationChanged(position);
}

// SplitPaneDelegate :: Private Static Data Member. ----------------------------

jmethodID SplitPaneDelegate::sm_dividerLocationChangedMID = 0;
